<?php
/*

  $Id: sasmallparcel.php,v 0.1 2003/04/15 Charles Oertel

  Catalog Side / Includes / Modules / Shipping
  osCommerce, Open Source E-Commerce Solutions
  http://www.oscommerce.com

  Copyright (c) 2003 Charles Oertel for FineBushPeople.net

  Released under the GNU General Public License

  USAGE
  This module calculates shipping for small parcels according to the South
  African letter post rates.  These distinguish between two zones:

  Southern Africa : Angola, Botswana, Burundi, Comoros, Congo (Dem Rep)
  Congo (Peoples Rep), Gabon, Kenya, Lesotho, Madagascar, Malawi,
  Mauritius, Mozambique, Namibia, Reunion, Rwanda, Seychelles, Swaziland,
  Tanzania, Uganda, Zambia and Zimbabwe, and...
  The rest of the world : (except South Africa).

  The postage is calculated at a fixed rate for every 100g of weight of
  the parcel.  

  Return values are:
  - Country not ZA, parcel weight < maximum : a quote for surface- and 
    airmail
  - Country not ZA, parcel weight > maximum : a message showing basket
    weight, weight limit, and saying that the weight exceeds the weight
    limit for this shipping option.  The radio button to select this option
    does not appear.
  - Country = ZA : $quote = false.  The option does not even appear on the
    checkout page.

  ACTIVATION AND CONFIGURATION

  To activate the module: go to the Admin screen, click on Modules,
  then click on Shipping.  A list of all shipping modules should appear.
  Click on the green dot next to the one labeled 'SA Letter Post rates 
  for small parcels'.  A list of settings will appear to the right.  
  Click on the Edit button.

  PLEASE NOTE THAT YOU WILL LOSE YOUR CURRENT SHIPPING RATES AND OTHER
  SETTINGS IF YOU TURN OFF THIS SHIPPING METHOD.  Make sure you keep a
  backup of your shipping settings somewhere at all times.

  NOTE: All weight units are assumed to be grams.

  You get to set global variables that apply to both Southern African and 
  other countries:
  - Weight that cost rates apply to: currently the postage is charged for
    every 100g of weight.  This value may change and can be set here.
  - Maximum weight allowed: currently small parcel postage is limited to
    2kg (2000g).  You can set this limit here.  If the items in the basket
    exceed this weight, the postage option is disabled with a message that
    the basket weight exceeds the permissable weight for small parcels (you
    edit this message in catalog/includes/languanges/english/
    sasmallparcel.php).

  For each of the shipping zones you can set the following:

  - Zone 1 Countries: Which countries are in Southern Africa. They should be
    entered as two character ISO country codes in all capital letters.
    They should be separated by commas with no spaces or other punctuation. 
    For example:
    AO,BW,BI,KM,CG,ZR,GA,KE,LS,MG,MW,MU,MZ,NA,RE,RW,SC,SZ,TZ,UG,ZM,ZW
  - Zone 1 Airmail Shipping Rates: The airmail cost per (weight that cost
    rate applies to (set above)) to Southern African countries.
  - Zone 1 Surfacemail Shipping Rates: The surfacemail cost per (weight that
    cost rate applies to (set above)) to Southern African countries.
  - Zone 1 Handling Fee: constant handling fee for shipping to Southern
    African countries.
  - Zone 1 Airmail Registration Fee: the cost of registering a small parcel
    for delivery by airmail to Southern African countries.
  - Zone 1 Surfacemail Registration Fee: the cost of registering a small 
    parcel for delivery by surface mail to Southern African countries.
  
  For the last zone, the settings are the same as above except that it will
  dump any country not found in previous zones into the last one.  You need
  not supply a list of country codes.

  NOTES ON ADAPTING THIS MODULE TO OTHER CASES:
  - This module was crafted from the zonesworld.php module submitted
    by elarifr
  - You can provide more zones by editing $this->num_zones in the constructor
  - If you change the country of origin, you need to change code that refers
    to South Africa (ZA) in this place in the quote:
      if ($dest_country == 'ZA') {
  - There are three behaviours you can elicit at the checkout page:
    i   :: the quote appears and can be selected,
    ii  :: the title for the shipping method appears, but there is an error
           message and the shipping method cannot be selected, or
    iii :: the shipping method does not appear at all.
    
    To get i, example code looks like this:
      $this->quotes = array(
        'id' => $this->code,
        'module' => MODULE_SHIPPING_SASMALLPARCEL_TEXT_TITLE,
        'methods' => array(
          array(
            'id' => $this->code,
            'title' => $surfacemail_shipping_method,
            'cost' => $surfacemail_shipping_cost),
          array(
            'id' => $this->code,
            'title' => $airmail_shipping_method,
            'cost' => $airmail_shipping_cost)));

    To get ii, example code looks like this:
      $this->quotes = array(
        'id' => $this->code,
        'module' => MODULE_SHIPPING_SASMALLPARCEL_TEXT_TITLE,
        'methods' => array(
          array('title' => $this->quotes['error'])));
      $this->quotes['error'] = $shipping_weight . ' ' . 
                               MODULE_SHIPPING_SASMALLPARCEL_TEXT_UNITS . ' ' . 
                               MODULE_SHIPPING_SASMALLPARCEL_EXCEEDED_WEIGHT . ' ' . 
                               MODULE_SHIPPING_SASMALLPARCEL_MAX_WEIGHT . ' ' . 
                               MODULE_SHIPPING_SASMALLPARCEL_TEXT_UNITS;

    To get iii, example code looks like this:
      return false;   //'Letter Post is not available for destinations in South Africa.';
*/

  class sasmallparcel {
    var $code, $title, $description, $enabled, $num_zones;

// class constructor
    function sasmallparcel() {
    /**************************************************************************
    *                             Constructor                                 *
    **************************************************************************/
      $this->code = 'sasmallparcel';
      $this->title = MODULE_SHIPPING_SASMALLPARCEL_TEXT_TITLE;
      $this->description = MODULE_SHIPPING_SASMALLPARCEL_TEXT_DESCRIPTION;
      $this->sort_order = MODULE_SHIPPING_SASMALLPARCEL_SORT_ORDER;
      $this->icon = '';
      $this->tax_class = MODULE_SHIPPING_SASMALLPARCEL_TAX_CLASS;
      $this->enabled = ((MODULE_SHIPPING_SASMALLPARCEL_STATUS == 'True') ? true : false);

      // CUSTOMIZE THIS SETTING FOR THE NUMBER OF ZONES NEEDED
      $this->num_zones = 2;
    }

// class methods
    function quote($method = '') {
    /**************************************************************************
    *                                Quote                                    *
    * Purpose: Calculate shipping costs and options during checkout           *
    * Input  : order - the order object
    *          shipping_weight - the total weight of the order
    * Output : quote populated with options when all correct,
    *          quote populated with an error message when weight limit exceeded
    *          quote = false when invalid country
    * Created: Charles Oertel 04/2003 (charles@finebushpeople.net)
    **************************************************************************/
      global $order, $shipping_weight;

      $dest_country = $order->delivery['country']['iso_code_2'];
      if ($dest_country == 'ZAR') {
          return false;   //'Letter Post is not available for destinations in South Africa.';
      }

      if ($shipping_weight > MODULE_SHIPPING_SASMALLPARCEL_MAX_WEIGHT) { 
        $this->quotes = array('id' => $this->code,
                              'module' => MODULE_SHIPPING_SASMALLPARCEL_TEXT_TITLE,
                              'methods' => array(array('title' => $this->quotes['error'])));
        $this->quotes['error'] = $shipping_weight . ' ' . 
                                 MODULE_SHIPPING_SASMALLPARCEL_TEXT_UNITS . ' ' . 
                                 MODULE_SHIPPING_SASMALLPARCEL_EXCEEDED_WEIGHT . ' ' . 
                                 MODULE_SHIPPING_SASMALLPARCEL_MAX_WEIGHT . ' ' . 
                                 MODULE_SHIPPING_SASMALLPARCEL_TEXT_UNITS;
        return $this->quotes;
      }

      $dest_zone = 0;
      $error = false;

      for ($i=1; $i<=$this->num_zones; $i++) {
        $countries_table = constant('MODULE_SHIPPING_SASMALLPARCEL_COUNTRIES_' . $i);
        $country_zones = split("[,]", $countries_table);
        if (in_array($dest_country, $country_zones)) {
          $dest_zone = $i;
          break;
        }
      }

      if ($dest_zone == 0) {
        $dest_zone = $this->num_zones;    // the zone is the last zone available
      }

      $surfacemail_cost = constant('MODULE_SHIPPING_SASMALLPARCEL_SURFACEMAIL_COST_' . $dest_zone);
      $surfacemail_shipping = ceil($shipping_weight/MODULE_SHIPPING_SASMALLPARCEL_COSTING_UNIT) * $surfacemail_cost;
      $surfacemail_shipping += constant('MODULE_SHIPPING_SASMALLPARCEL_SURFACEMAIL_REGISTRATIONFEE_' . $dest_zone);
      $surfacemail_shipping += constant('MODULE_SHIPPING_SASMALLPARCEL_HANDLING_' . $dest_zone);
      $surfacemail_shipping_method = MODULE_SHIPPING_SASMALLPARCEL_TEXT_SURFACEMAIL_WAY . ' ' . 
                                     $dest_country . ' : ' . $shipping_weight . ' ' . 
                                     MODULE_SHIPPING_SASMALLPARCEL_TEXT_UNITS . ' - ' .
                                     MODULE_SHIPPING_SASMALLPARCEL_TEXT_SURFACEMAIL_DELIVERYTIME;

      $airmail_cost = constant('MODULE_SHIPPING_SASMALLPARCEL_AIRMAIL_COST_' . $dest_zone);
      $airmail_shipping = ceil($shipping_weight/MODULE_SHIPPING_SASMALLPARCEL_COSTING_UNIT) * $airmail_cost;
      $airmail_shipping += constant('MODULE_SHIPPING_SASMALLPARCEL_AIRMAIL_REGISTRATIONFEE_' . $dest_zone);
      $airmail_shipping += constant('MODULE_SHIPPING_SASMALLPARCEL_HANDLING_' . $dest_zone);
      $airmail_shipping_method = MODULE_SHIPPING_SASMALLPARCEL_TEXT_AIRMAIL_WAY . ' ' . 
                                 $dest_country . ' : ' . $shipping_weight . ' ' . 
                                 MODULE_SHIPPING_SASMALLPARCEL_TEXT_UNITS . ' - ' .
                                 MODULE_SHIPPING_SASMALLPARCEL_TEXT_AIRMAIL_DELIVERYTIME;
      $methods = array();

      if (($method=='surfacemail') or ($method=='')) {
          $methods[] = array( 'id' => 'surfacemail',
                              'title' => $surfacemail_shipping_method,
                              'cost' => $surfacemail_shipping);
      }
      if (($method=='airmail') or ($method=='')) {
          $methods[] = array( 'id' => 'airmail',
                              'title' => $airmail_shipping_method,
                              'cost' => $airmail_shipping);
      }

      $this->quotes = array( 'id' => $this->code,
                             'module' => MODULE_SHIPPING_SASMALLPARCEL_TEXT_TITLE,
                             'methods' => $methods);

      if ($this->tax_class > 0) {
        $this->quotes['tax'] = tep_get_tax_rate($this->tax_class, $order->delivery['country']['id'], $order->delivery['zone_id']);
      }

      if (tep_not_null($this->icon)) $this->quotes['icon'] = tep_image($this->icon, $this->title);
      if ($error == true) $this->quotes['error'] = MODULE_SHIPPING_SASMALLPARCEL_INVALID_ZONE;

      return $this->quotes;
    }

    function check() {
    /**************************************************************************
    *                                 Check                                   *
    **************************************************************************/
      if (!isset($this->_check)) {
        $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_SHIPPING_SASMALLPARCEL_STATUS'");
        $this->_check = tep_db_num_rows($check_query);
      }
      return $this->_check;
    }

    function install() {
    /**************************************************************************
    *                               Install                                   *
    * Purpose: Creates the correct keys in the configuration table for 
    *          automatic presentation of variables etc.  Pay attention to
    *          the key names and ensure they are returned by the keys() method
    *          below.
    * Output : Table populated with the keys (constants) and set to default
    *          values for South African small parcel letter post rates.
    * Remarks: This is where you define, and initialise all your constants and
    *          administrator-defined variables.
    **************************************************************************/
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) VALUES ('Enable SA Letter Post', 'MODULE_SHIPPING_SASMALLPARCEL_STATUS', 'True', 'Do you want to offer South African Letter Post shipping?', '6', '0', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort order of display.', 'MODULE_SHIPPING_SASMALLPARCEL_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '0', now())");
     tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Tax Class', 'MODULE_SHIPPING_SASMALLPARCEL_TAX_CLASS', '0', 'Use the following tax class on the shipping fee.', '6', '0', 'tep_get_tax_class_title', 'tep_cfg_pull_down_tax_classes(', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Maximum weight allowed.', 'MODULE_SHIPPING_SASMALLPARCEL_MAX_WEIGHT', '2000', 'Maximum allowed Letter Post parcel weight in grams.', '6', '0', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Weight or portion thereof that cost rates apply to.', 'MODULE_SHIPPING_SASMALLPARCEL_COSTING_UNIT', '100', 'The unit of weight that the costing rate applies to (e.g. R9.20 per X MODULE_SHIPPING_SASMALLPARCEL_TEXT_UNITS).', '6', '0', now())");
      for ($i = 1; $i <= $this->num_zones; $i++) {
        $default_countries = '';
        if ($i == 1) {
          $default_countries = 'AO,BW,BI,KM,CG,ZR,GA,KE,LS,MG,MW,MU,MZ,NA,RE,RW,SC,SZ,TZ,UG,ZM,ZW';
          $airmail_rate_per_unit = '9.20';
          $surfacemail_rate_per_unit = '7.20';
        }
        if ($i == 2) {
          $default_countries = 'All Others'; // this must be the last zone
          $airmail_rate_per_unit = '16.30';
          $surfacemail_rate_per_unit = '8.20';
        }
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Zone " . $i ." Countries', 'MODULE_SHIPPING_SASMALLPARCEL_COUNTRIES_" . $i ."', '" . $default_countries . "', 'Comma separated list of two character ISO country codes that are part of Zone " . $i . ".', '6', '0', now())");
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Zone " . $i ." Airmail shipping rates', 'MODULE_SHIPPING_SASMALLPARCEL_AIRMAIL_COST_" . $i ."', '" . $airmail_rate_per_unit . "', 'Airmail rate per unit to Zone " . $i . " destinations. Example: 9.20 (rand per 100g).', '6', '0', now())");
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Zone " . $i ." Surface mail shipping rates', 'MODULE_SHIPPING_SASMALLPARCEL_SURFACEMAIL_COST_" . $i ."', '" . $surfacemail_rate_per_unit . "', 'Surface mail rate per unit to Zone " . $i . " destinations. Example: 9.20 (rand per 100g).', '6', '0', now())");
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Zone " . $i ." Handling Fee', 'MODULE_SHIPPING_SASMALLPARCEL_HANDLING_" . $i ."', '0', 'Handling Fee for this shipping zone', '6', '0', now())");
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Zone " . $i ." Airmail registration Fee', 'MODULE_SHIPPING_SASMALLPARCEL_AIRMAIL_REGISTRATIONFEE_" . $i ."', '15.00', 'SA Airmail Postal Registration Fee for this shipping zone', '6', '0', now())");
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Zone " . $i ." Surfacemail registration Fee', 'MODULE_SHIPPING_SASMALLPARCEL_SURFACEMAIL_REGISTRATIONFEE_" . $i ."', '15.00', 'SA Surface mail Postal Registration Fee for this shipping zone', '6', '0', now())");
      }
    }

    function remove() { 
    /**************************************************************************
    *                                Remove                                   *
    * Purpose: Deletes all the configuration keys
    **************************************************************************/
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')");
    }

    function keys() {
    /**************************************************************************
    *                                Remove                                   *
    * Purpose: Returns all the keys used by this module.
    **************************************************************************/
      $keys = array('MODULE_SHIPPING_SASMALLPARCEL_STATUS', 
                    'MODULE_SHIPPING_SASMALLPARCEL_SORT_ORDER', 
                    'MODULE_SHIPPING_SASMALLPARCEL_TAX_CLASS', 
                    'MODULE_SHIPPING_SASMALLPARCEL_COSTING_UNIT', 
                    'MODULE_SHIPPING_SASMALLPARCEL_MAX_WEIGHT');

      for ($i=1; $i<=$this->num_zones; $i++) {
        $keys[] = 'MODULE_SHIPPING_SASMALLPARCEL_COUNTRIES_' . $i;
        $keys[] = 'MODULE_SHIPPING_SASMALLPARCEL_AIRMAIL_COST_' . $i;
        $keys[] = 'MODULE_SHIPPING_SASMALLPARCEL_SURFACEMAIL_COST_' . $i;
        $keys[] = 'MODULE_SHIPPING_SASMALLPARCEL_HANDLING_' . $i;
        $keys[] = 'MODULE_SHIPPING_SASMALLPARCEL_AIRMAIL_REGISTRATIONFEE_' . $i;
        $keys[] = 'MODULE_SHIPPING_SASMALLPARCEL_SURFACEMAIL_REGISTRATIONFEE_' . $i;
      }

      return $keys;
    }
  }
?>
